﻿namespace SenenFernandez.SmartExtensionMethods.Interactivity
{
    using System;
    using System.Windows.Controls;
    using System.Windows;

    /// <summary>
    /// SmartWindow class.
    /// </summary>
    public class SmartWindow : TriggerAction<FrameworkElement>
    {
        /// <summary>
        /// The child window to display as part of the dialog.
        /// </summary>
        public static readonly DependencyProperty WindowTypeProperty =
            DependencyProperty.Register("WindowType", typeof(Type), typeof(SmartWindow), new PropertyMetadata(null));

        /// <summary>
        /// The <see cref="ControlTemplate"/> to apply to the dialog content.
        /// </summary>
        public static readonly DependencyProperty ContentTemplateProperty =
            DependencyProperty.Register("ContentTemplate", typeof(ControlTemplate), typeof(SmartWindow), new PropertyMetadata(null));

        /// <summary>
        /// The <see cref="Style"/> to apply to the dialog content.
        /// </summary>
        public static readonly DependencyProperty StyleProperty =
            DependencyProperty.Register("Style", typeof(Style), typeof(SmartWindow), new PropertyMetadata(null));

        /// <summary>
        /// The child window to display as part of the dialog.
        /// </summary>
        public static readonly DependencyProperty IsModalProperty =
            DependencyProperty.Register("IsModal", typeof(bool), typeof(SmartWindow), new PropertyMetadata(true));

        /// <summary>
        /// The DataContext to apply to the dialog content.
        /// </summary>
        public static readonly DependencyProperty DataContextProperty =
            DependencyProperty.Register("DataContext", typeof(object), typeof(SmartWindow), new PropertyMetadata(null));

        private Window childWindow;

        /// <summary>
        /// Gets or sets the child window modal.
        /// </summary>
        public Type WindowType
        {
            get { return (Type)GetValue(WindowTypeProperty); }
            set { SetValue(WindowTypeProperty, value); }
        }

        /// <summary>
        /// Gets or sets the Style for a default child window.
        /// </summary>
        public Style Style
        {
            get { return (Style)GetValue(StyleProperty); }
            set { SetValue(StyleProperty, value); }
        }

        /// <summary>
        /// Gets or sets the content template for a default child window.
        /// </summary>
        public ControlTemplate ContentTemplate
        {
            get { return (ControlTemplate)GetValue(ContentTemplateProperty); }
            set { SetValue(ContentTemplateProperty, value); }
        }

        /// <summary>
        /// Gets or sets the modal for a default child window.
        /// </summary>
        public bool IsModal
        {
            get { return (bool)GetValue(IsModalProperty); }
            set { SetValue(IsModalProperty, value); }
        }

        /// <summary>
        /// Gets or sets the DataContext for a default child window.
        /// </summary>
        public object DataContext
        {
            get { return GetValue(DataContextProperty); }
            set { SetValue(DataContextProperty, value); }
        }

        /// <summary>
        /// Returns the child window to display as part of the trigger action.
        /// </summary>
        protected Window GetChildWindow(Notification dataContext)
        {
            Window window;
            if (WindowType != null)
            {
                window = (Window)Activator.CreateInstance(WindowType);
                window.DataContext = dataContext;
            }
            else
            {
                window = new Window
                {
                    Style = Style,
                    Template = ContentTemplate,
                    WindowStartupLocation = WindowStartupLocation.CenterScreen,
                    DataContext = DataContext ?? dataContext.Content,
                };
            }
            return window;
        }

        /// <summary>
        /// Displays the child window and collects results for <see cref="IInteractionRequest"/>.
        /// </summary>
        /// <param name="parameter">The parameter to the action. 
        /// If the action does not require a parameter, the parameter may be set to a null reference.</param>
        protected override void Invoke(object parameter)
        {
            var args = parameter as InteractionRequestedEventArgs;
            if (args != null)
            {
                if (childWindow == null)
                {
                    childWindow = GetChildWindow(args.Context);
                    var callback = args.Callback;
                    EventHandler[] handler = { null };
                    handler[0] = (sender, e) =>
                    {
                        childWindow.Closed -= OnChildWindowClosed;
                        callback();
                    };
                    childWindow.Closed += OnChildWindowClosed;
                }
                if (IsModal)
                {
                    childWindow.ShowDialog();
                }
                else
                {
                    childWindow.RestoreWindow();
                }
            }
        }

        private void OnChildWindowClosed(object sender, EventArgs e)
        {
            childWindow = null;
        }
    }
}